# Copyright (C) 2008 Marcin Cieslik <marcin.cieslik@gmail.com>
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA

from ckd3 cimport kdnode, kdpoint, swap, points, DTYPE_t, knn, build_tree, qsort, dist, kdtree
from stdlib cimport malloc, free
import numpy as np
cimport numpy as np

def test_swap(np.ndarray[DTYPE_t, ndim =2] A):
    cdef unsigned int size = A.size
    cdef unsigned int pnts = A.shape[0]
    cdef unsigned int dims = A.shape[1]
    cdef np.ndarray n_array = A.reshape((size,))
    cdef DTYPE_t *c_array = <DTYPE_t *>n_array.data
    cdef kdpoint *point_list = points(c_array, pnts, dims)
    cdef unsigned int i
    cdef DTYPE_t sum_zero =0.0
    for 0 <= i < pnts >> 1:
        swap(&point_list[i], &point_list[pnts - i - 1])
    for 0<= i < pnts:
        for 0<=j < size/pnts:
            sum_zero += point_list[i].coords[j] - n_array[(pnts - i - 1)*size/pnts + j]
    return sum_zero

def test_dist():
    from random import random
    cdef kdpoint a, b, c,
    cdef DTYPE_t h
    cdef unsigned int i
    a.coords = <DTYPE_t *>malloc(sizeof(DTYPE_t)*3)
    a.coords[0] = 1.0; a.coords[1] = 1.0; a.coords[2] = 1.0
    b.coords = <DTYPE_t *>malloc(sizeof(DTYPE_t)*3)
    b.coords[0] = 2.0; b.coords[1] = 2.0; b.coords[2] = 2.0
    c.coords = <DTYPE_t *>malloc(sizeof(DTYPE_t)*3)
    c.coords[0] = 1.0; c.coords[1] = 1.0; c.coords[2] = 1.0
    # should be 0.0
    h = dist(&a, &b, 2) - 2 + dist(&a, &c, 2)
    free(a.coords)
    free(b.coords)
    free(c.coords)
    return h

def test_points(np.ndarray[DTYPE_t, ndim =2] A):
    cdef unsigned int size = A.size
    cdef unsigned int pnts = A.shape[0]
    cdef unsigned int dims = A.shape[1]
    cdef np.ndarray n_array = A.reshape((size,))
    cdef DTYPE_t *c_array = <DTYPE_t *>n_array.data
    cdef kdpoint *point_list = points(c_array, pnts, dims)
    cdef unsigned int i, j
    cdef DTYPE_t sum_zero =0.0
    for 0<= i < pnts:
        for 0<=j < size/pnts:
            sum_zero += point_list[i].coords[j] - n_array[i*size/pnts + j]
    return sum_zero

def test_qsort(np.ndarray[DTYPE_t, ndim =2] A):
    cdef unsigned int size = A.size
    cdef unsigned int pnts = A.shape[0]
    cdef unsigned int dims = A.shape[1]
    cdef np.ndarray n_array2 = A.copy()
    cdef np.ndarray n_array = A.reshape((size,))
    cdef DTYPE_t *c_array = <DTYPE_t *>n_array.data
    cdef kdpoint *point_list = points(c_array, pnts, dims)
    cdef unsigned int i, j
    qsort(point_list, 0, pnts-1, 0)
    n_array2.sort(axis=0)
    for 0<= i < pnts:
        if point_list[i].coords[0] - n_array2[i,0] != 0.0:
            return 1
    return 0


def test_knn(np.ndarray[DTYPE_t, ndim =2] A, np.ndarray[DTYPE_t, ndim =1] a):
    ### TEST 1 ###
    # test if knn returns all if k == number of points
    cdef unsigned int pnts = A.shape[0]
    kdt = kdtree(A)
    R = kdt.knn(a, pnts)[0]
    R.sort()
    for 1 <= i < pnts:
        if R[i] - R[i-1] != 1:
            return 1
    return 0

def test_rn(np.ndarray[DTYPE_t, ndim =2] A):
    return 0
